﻿
using Linphone;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;

namespace Firearms
{
    internal class MyLinPhone
    {
        private Core core;
        private Factory factory;
        private Call call;
        private System.Timers.Timer t;
        private string info = "";

        private PictureBox pictureBox_video;
        private UIAvatar btnHangUp;
        private UIAvatar btnAcceptCall;
        private String host;
        private String username;
        private String pwd;
        private string _messageText;
        public string CreateTemplateMessage
        {
            get { return _messageText; }
            set
            {
                if (_messageText != value)
                {
                    
                    _messageText = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(value));
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public MyLinPhone(PictureBox pictureBox_video, String host, String username, String pwd, UIAvatar btnHangUp, UIAvatar btnAcceptCall)
        {
            this.pictureBox_video = pictureBox_video;
            this.btnAcceptCall = btnAcceptCall;
            this.btnHangUp = btnHangUp;
            this.host = host;
            this.username = username;
            this.pwd = pwd;
            if (core == null)
            {
                sip_init();
                if (pictureBox_video.InvokeRequired)
                {
                    pictureBox_video.Invoke(new Action(sip_init));
                    return;
                }
            }
            else
            {
                return;
            }
        }

        public void sip_init()
        {
            if (factory != null)
            {
                MessageBox.Show("sip资源已存在");
                return;
            }

            factory = Factory.Instance;
            core = factory.CreateCore(new CoreListener() { }, "linphonerc", "linphonerc-factory");
            core.AvpfMode = AVPFMode.Disabled;
            Core.EnableLogCollection(LogCollectionState.Disabled);
            core.Listener.OnRegistrationStateChanged = OnRegistration;
            core.Listener.OnCallStateChanged = OnCallState;
            core.Listener.OnMessageReceived = OnMessage;

            //设置本地运行端口
            Linphone.Transports tt = factory.CreateTransports();
            tt.UdpPort = 6060;
            core.Transports = tt;
            string x = "";
            info = "遍历所有视频设备";
            foreach (string s in core.VideoDevicesList)
            {
                info += "\r\nset=" + s;
                if (s.IndexOf("Camera") != -1)
                {
                    // bctbx-error-bctbx_file_open: Error open Permission denied
                    x = s;
                }
            }
            if (x != "")
            {
                info += "\r\n绑定视频设备：" + x;
                core.VideoDevice = x;//"Directshow capture: Integrated Camera"; //摄像头设置
            }
            info += "\r\n缺省音频输入设备：" + core.DefaultInputAudioDevice.DeviceName;
            info += "\r\n缺省音频输出设备：" + core.DefaultOutputAudioDevice.DeviceName;

            info += "\r\n遍历扩展音频设备：";
            foreach (AudioDevice s in core.ExtendedAudioDevices)
            {
                info += "\r\n" + s.DeviceName;
            }
            core.SetUserAgent("mylinphone", "1.0");


            //info += "\r\n当前音频输入设备：" + core.InputAudioDevice.DeviceName;
            //info += "\r\n当前音频输出设备：" + core.OutputAudioDevice.DeviceName;



            info += "\r\n编码关闭和启用";
            foreach (PayloadType p in core.AudioPayloadTypes)
            {
                if (p.MimeType == "opus") { p.Enable(false); }//编码关闭和启用
                if (p.MimeType == "GSM") { p.Enable(true); }//编码关闭和启用
                info += "\r\n" + p.MimeType + "(" + p.Enabled() + ")";
            }

            info += "\r\n视频参数";
            foreach (PayloadType p in core.VideoPayloadTypes)
            {
                if (p.MimeType == "VP8") { p.Enable(true); }
                if (p.MimeType == "H264") { p.Enable(false); }
                info += "\r\n" + p.MimeType + "(" + p.Enabled() + ")";
            }

            t = new System.Timers.Timer(20);   //实例化Timer类，设置间隔时间为10000毫秒；   
            t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到达时间的时候执行事件；   
            t.AutoReset = true;   //设置是执行一次（false）还是一直执行(true)；   
            t.Enabled = true;     //是否执行System.Timers.Timer.Elapsed事件；   

            //本地运行端口  也是本地呼叫的端口 本地呼叫需要关闭ip6 
            core.Ipv6Enabled = false;

            //richTextBox_info.Text = info;
            info = "";
            core.NativeVideoWindowId = pictureBox_video.Handle;//video window set

        }

        private void theout(object sender, ElapsedEventArgs e)
        {
            //core.Iterate();

            if (pictureBox_video.IsHandleCreated)
            {
                pictureBox_video.Invoke(new EventHandler(delegate
                {
                    core.Iterate();
                }));
            }




        }

        private void OnMessage(Core lc, ChatRoom room, ChatMessage message)
        {
            info += "\r\nOnMessage: " + message;

        }

        private void OnCallState(Core lc, Call call, CallState cstate, string message)
        {
            this.CreateTemplateMessage = message;
            Console.WriteLine( cstate  + "修改了变量");
            //接收到电话但是未接通
            if (message == "Incoming CallSession")
            {
                Show_video(true,true);
            }
            //呼出电话但是未接通
            else if (message == "Starting outgoing call")
            {
                Show_video(true,false);

            }
            //通话被拒绝。在电话通话过程中，当你发起呼叫并且被叫方拒绝接听或无法接听时
            else if (message == "Call declined")
            {
               Show_video(false,false);
            }
            //通话双方正在进行实时语音通信
            else if (message == "Streams running")
            {
                btnAcceptCall.Visible = false;
            }
            //通话结束
            else if (message == "Call ended")
            {
               Show_video(false,false);
            }
            //通话被终止或结束的状态
            else if (message == "Call terminated")
            {
                Show_video(false,false);
            }
            //通话不成功
            else if (message == "Not Found")
            {
                Show_video(false,false);
            }
            else if (message == "Call released")
            {
                Show_video(false,false);
            }else if(message == "Outgoing call in progress")
            {
                btnAcceptCall.Visible = false;
            }
        }
        //显示通话工具
        private void Show_video(bool show, bool show1)
        {
            if (show)
            {
                if (pictureBox_video.InvokeRequired)
                {
                    btnHangUp.Invoke(new Action(() => btnHangUp.Visible = true));
                    btnHangUp.Invoke(new Action(() => btnHangUp.BringToFront()));
                    if (show1)
                    {
                        btnAcceptCall.Invoke(new Action(() => btnAcceptCall.Visible = true));
                        btnAcceptCall.Invoke(new Action(() => btnAcceptCall.BringToFront()));
                    }
                    
                }
                else
                {
                    btnHangUp.Visible = true;
                    btnAcceptCall.Visible = true;
                    btnAcceptCall.BringToFront();
                    btnHangUp.BringToFront();
                }
               
            }
            else
            {
                btnHangUp.Visible = false;
                btnAcceptCall.Visible = false;
                btnAcceptCall.BringToFront();
            }
           
        }
        private void OnRegistration(Core lc, ProxyConfig cfg, RegistrationState cstate, string message)
        {
            info += "\r\nOnRegistration: " + message;

        }

        public void Reg(String username)
        {

            foreach (AuthInfo a in core.AuthInfoList)
            {
                core.RemoveAuthInfo(a);
            }
            foreach (ProxyConfig a in core.ProxyConfigList)
            {
                core.RemoveProxyConfig(a);
            }

            AuthInfo authInfo = factory.CreateAuthInfo(username, username, pwd, null, null, host);
            core.AddAuthInfo(authInfo);
            var proxyConfig = core.CreateProxyConfig();

            proxyConfig.Edit();

            String sipurl = "sip:" + username + "@" + host;
            var identity = factory.CreateAddress(sipurl);
            Console.WriteLine(sipurl, pwd, host);

            proxyConfig.IdentityAddress = identity;
            proxyConfig.ServerAddr = sipurl;
            //  proxyConfig.Route = domain;

            proxyConfig.RegisterEnabled = true;
            proxyConfig.PublishEnabled = true;
            proxyConfig.AvpfMode = AVPFMode.Disabled;
            proxyConfig.Done();
            core.AddProxyConfig(proxyConfig);
            core.DefaultProxyConfig = proxyConfig;

        }

        public void close()
        {
            if (t != null)
                t.Stop();

            if (call != null && call.State == CallState.Connected)
            {
                call.Terminate();
            }
            if (core != null)
            {
                core.Stop();
            }
        }

        public void callto(String tUser)
        {
            Show_video(true,false);
            call = core.CurrentCall;
            if (call != null)
            {
                core.TerminateCall(call);
            }
            CallParams callParams = core.CreateCallParams(null);
            callParams.VideoEnabled = true;
            Console.WriteLine("sip:" + tUser + "@" + host);
            call = core.InviteAddressWithParams(core.InterpretUrl("sip:" + tUser + "@" + host), callParams);
        }

        public void callaccept()
        {
            call = core.CurrentCall;
            if (call != null)
            {
                call.Accept();
            }
        }

        public void callstop()
        {
            call = core.CurrentCall;
            if (call != null)
            {
                core.TerminateAllCalls();
            }
        }
    }
}
